<?php
/**
 * 零起飞-(07FLY-CRM)
 * ==============================================
 * 版权所有 2015-2028   成都零起飞网络，并保留所有权利。
 * 网站地址: http://www.07fly.xyz
 * ----------------------------------------------
 * 如果商业用途务必到官方购买正版授权, 以免引起不必要的法律纠纷.
 * ==============================================
 * Author: kfrs <goodkfrs@QQ.com> 574249366
 * Date: 2019-10-3
 */

namespace app\ten\logic;

/**
 * 租户模块逻辑
 */
class TenModule extends TenBase
{

    private $app_path = '';
    private $app_upload_path = '';
    private $app_pack_path = '';
    private $app_download_path = '';

    public function __construct()
    {
        $this->initModuleDir();
    }

    /**
     * 初始模块目录
     * @param $module
     * @return string
     * Author: lingqifei created by at 2020/6/4 0004
     */
    public function initModuleDir()
    {
        //应用模块目录
        $path = PATH_APP;
        !is_dir($path) && mkdir($path, 0755, true);
        $this->app_path = $path;

        //模块包上传目录
        $path = PATH_DATA . 'app' . DS . 'upload' . DS;
        !is_dir($path) && mkdir($path, 0755, true);
        $this->app_upload_path = $path;

        //模块打包目录
        $path = PATH_DATA . 'app/zippack/';
        !is_dir($path) && mkdir($path, 0755, true);
        $this->app_pack_path = $path;

        //模块下载目录
        $path = PATH_DATA . 'app' . DS . 'download' . DS;
        !is_dir($path) && mkdir($path, 0755, true);
        $this->app_download_path = $path;
    }

    /**
     * 获取权限分组列表
     */
    public function getTenModuleList($where = [], $field = true, $order = 'sort asc', $paginate = DB_LIST_ROWS)
    {
        $list = $this->modelTenModule->getList($where, $field, $order, $paginate);
        return $list;
    }

    /**
     * 租户模块添加
     */
    public function tenModuleAdd($data = [])
    {
        $validate_result = $this->validateTenModule->scene('add')->check($data);
        if (!$validate_result) {
            return [RESULT_ERROR, $this->validateTenModule->getError()];
        }
        $url = url('show');
        $result = $this->modelTenModule->setInfo($data);
        $result && action_log('新增', '新增模块，name：' . $data['name']);
        return $result ? [RESULT_SUCCESS, '添加成功', $url] : [RESULT_ERROR, $this->modelTenModule->getError()];
    }

    /**
     * 租户模块编辑
     */
    public function tenModuleEdit($data = [])
    {
        $validate_result = $this->validateTenModule->scene('edit')->check($data);
        if (!$validate_result) {
            return [RESULT_ERROR, $this->validateTenModule->getError()];
        }
        $url = url('show');
        $result = $this->modelTenModule->setInfo($data);
        $result && action_log('编辑', '编辑租户模块，name：' . $data['name']);
        return $result ? [RESULT_SUCCESS, '编辑成功', $url] : [RESULT_ERROR, $this->modelTenModule->getError()];
    }

    /**
     * 租户模块删除
     */
    public function tenModuleDel($where = [])
    {
        $result = $this->modelTenModule->deleteInfo($where, true);
        $result && action_log('删除', '删除租户模块，where：' . http_build_query($where));
        return $result ? [RESULT_SUCCESS, '删除成功'] : [RESULT_ERROR, $this->modelTenModule->getError()];
    }

    /**
     * 获取租户模块信息
     */
    public function getTenModuleInfo($where = [], $field = true)
    {
        $info = $this->modelTenModule->getInfo($where, $field);
        if (!empty($info)) {
            $info['menu_list'] = $this->modelTenModuleMenu->getColumn(['ten_module_id' => $info['id']], 'ten_menu_id');
        }
        return $info;
    }

    /**
     * 设置用户组权限节点
     */
    public function setTenModuleMenus($data = [])
    {
        if (empty($data['menu_ids']) || empty($data['id'])) {
            throw_response_error('参数错误');
        }
        $menuIds = $data['menu_ids'];
        $updata = [];
        foreach ($menuIds as $menuId) {
            $updata[] = ['ten_module_id' => $data['id'], 'ten_menu_id' => $menuId];
        }
        $updata && $this->modelTenModuleMenu->deleteInfo(['ten_module_id' => $data['id']], true);
        $result = $this->modelTenModuleMenu->setList($updata);
        $url = url('show');
        return $result ? [RESULT_SUCCESS, '设置成功', $url] : [RESULT_ERROR, $this->modelTenModule->getError()];
    }

    /**
     * 已经选择租户模块
     */
    public function selectModuleList($module_list = [], $tenant_module_ids = [])
    {
        foreach ($module_list as &$info) {
            in_array($info['id'], $tenant_module_ids) ? $info['tag'] = 'active' : $info['tag'] = '';
        }
        return $module_list;
    }

    /**
     * 同步模块数据
     * @param $data
     * @return array
     * @author: 开发人生 goodkfrs@qq.com
     * @Time: 2025/3/31 14:38
     */
    public function tenModuleSyncTable($data = [])
    {
        //查询模块信息
        $info = $this->modelTenModule->getInfo(['id' => $data['id']], true);
        if (empty($info)) {
            return [RESULT_ERROR, '本模块数据不存在'];
            exit;
        }
        $module_name = $info['module'];
        //1、判断目录是否在
        $module_dir = $this->app_path . $module_name . DS;
        if (!is_dir($module_dir)) {
            return [RESULT_ERROR, '模块文件目录不存在'];
            exit;
        }
        //1、数据库同步
        $app_table_file = $module_dir . 'data' . DS . 'table.php';
        if (file_exists($app_table_file)) {
            $content = include($app_table_file);//加载table结构数组
            $table = new \lqf\SyncTableDesc($content, SYS_DB_PREFIX);
            $table->generate();
        }
        return [RESULT_SUCCESS, '文件同步完成', ''];
    }

    /**
     * 同步菜单
     * @param $data
     * @return array
     * @author: 开发人生 goodkfrs@qq.com
     * @Time: 2025/3/31 14:38
     */
    public function tenModuleSyncMenu($data = [])
    {
        //查询模块信息
        $info = $this->modelTenModule->getInfo(['id' => $data['id']], true);
        if (empty($info)) {
            return [RESULT_ERROR, '本模块数据不存在'];
            exit;
        }
        $module_name = $info['module'];

        //1、判断目录是否在
        $module_dir = $this->app_path . $module_name . DS;
        if (!is_dir($module_dir)) {
            return [RESULT_ERROR, '模块文件目录不存在'];
            exit;
        }
        //1、同步栏目
        $app_menu_file = $module_dir . 'data' . DS . 'menu.json';
        if (file_exists($app_menu_file)) {
            $content = file_get_contents($app_menu_file);
            $content = isJson($content, true);
            $this->modelTenMenu->tenMenuImport($content);
        }
        return [RESULT_SUCCESS, '文件同步完成', ''];
    }


    /**
     * 模块上传=》安装
     * @param array $data
     * Author: lingqifei created by at 2020/6/4 0004
     */
    public function tenModuleUpload($data = [])
    {
        $save_name = data_md5_key(time());//保存文件名称
        $save_file_path = $data['filename'];//zip包路径
        //zip文件,目录中解压，文件名以时间为准
        $module_tmp_dir = $this->app_upload_path . $save_name . DS;//以斜杠结束

        dlog('app解压安装=》===========================开始=====');

        if (file_exists($save_file_path)) {
            //1、解压目录
            $zip = new \lqf\Zip();
            $res = $zip->unzip($save_file_path, $module_tmp_dir);
            if ($res != true) {
                return [RESULT_ERROR, '模块包解压失败'];
            }
            //2、获取里面的文件包名
            $fp = new \lqf\Dir();
            $dirlist = $fp->listFile($module_tmp_dir);//查看目录列表文件，必须是以斜杠结束
            $app_path = !empty($dirlist) ? $dirlist[0]['pathname'] : '';
            $app_name = !empty($dirlist) ? $dirlist[0]['filename'] : '';
            if (empty($app_path)) {
                return [RESULT_ERROR, '应用插件压缩包缺少目录文件'];
            }
            dlog('zip包文件路径：' . $save_file_path);
            dlog('zip解压后目录：' . $module_tmp_dir);
            dlog('app目录：' . $app_path);

            //3、app目录执行安装
            return $this->tenModuleInstallExec($app_name, $app_path);

        } else {
            return [RESULT_ERROR, '模块目录中模块信息文件info.php不存在'];
            exit;
        }
    }


    /**
     * app安装执行=》目录
     * @param $app_path
     * @param $app_name
     * @return void
     * @author: 开发人生 goodkfrs@qq.com
     * @Time: 2022/12/29 9:40
     */
    public function tenModuleInstallExec($app_name, $app_path)
    {
        //模块配置文件
        $app_info_file = $app_path . '/data/info.php';
        $app_is_install = true;//是否安装,默认为安装
        dlog('app安装执行=》开始=====');

        if (file_exists($app_info_file)) {

            $moduel_info = include($app_info_file); //解压包中模块信息
            //第1步：判断模块是否存在,
            //1、不存在=》添加，
            //2、存在=》更新
            if (!empty($moduel_info['identifier'])) {

                $moduleData['name'] = $moduel_info['title'];
                $moduleData['module'] = $moduel_info['name'];
                $moduleData['identifier'] = $moduel_info['identifier'];

                $map['module'] = $app_name;
                $info = $this->modelTenModule->getInfo($map);
                if (empty($info)) {
                    $sys_mid = $this->modelTenModule->setInfo($moduleData);
                    dlog('install模块数据：' . $sys_mid);
                } else {
                    $sys_mid = $info['id'];
                    $this->modelTenModule->updateInfo(['id' => $sys_mid], $moduleData);
                    $app_is_install = false;//表示更新
                    dlog('upgrade模块数据：' . $sys_mid);
                }
            }
            //第2步：移动包到应用目录
            $module_dir = PATH_APP . $app_name . DS;
            $file = new \lqf\File();
            $result = $file->handle_dir($app_path, $module_dir, 'copy', true);
            if ($result == false) {
                return [RESULT_ERROR, '复制模块文件目录失败'];
                exit;
            }
            dlog('复制解压包=》app目录下：' . $sys_mid);

            //3、判断是否有栏目数据表同步文件 menu.json
            $app_menu_file = $app_path . '/data/menu.json';
            if (file_exists($app_menu_file)) {
                $content = file_get_contents($app_menu_file);
                $content = isJson($content, true);
                $this->modelTenMenu->tenMenuImport($content);
                dlog('3、同步文件 menu.json');
            }

            //4、判断是否有安装SQL脚本，执行安装脚本
            // SQL文件存在 && 未安装=》执行安装操作
            $app_sql_install_file = $app_path . DS . 'data' . DS . 'install.sql';
            if (file_exists($app_sql_install_file) && $app_is_install == true) {
                $this->modelDatabase->importModuleSqlExec(array('time' => time(), 'module_dir' => $module_dir . 'data' . DS, 'sqlfile' => 'install.sql'));
                dlog('4、同步文件 install.sql');
            }

            //4.1、是否升级表字段
            //4.1、数据库同步
            $app_table_file = $module_dir . 'data' . DS . 'table.php';
            if (file_exists($app_table_file)) {
                $content = include($app_table_file);//加载table结构数组
                $table = new \lqf\SyncTableDesc($content, SYS_DB_PREFIX);
                $table->generate();
                dlog('4.1、同步文件 table.php');
            }

            //4.2、判断是否有升级SQL脚本，执行升级脚本
            $app_sql_upgrade = $app_path . '/data/upgrade.sql';
            if (file_exists($app_sql_upgrade)) {
                $this->modelDatabase->importModuleSqlExec(array('time' => time(), 'module_dir' => $module_dir . 'data', 'sqlfile' => 'upgrade.sql'));
                dlog('4.3、同步文件 upgrade.sql');
            }

            //5、判断是模模板文件
            $app_theme_dir = $app_path . '/data/theme';//模模板目录
            if (is_dir($app_theme_dir)) {
                $theme_dir = PATH_PUBLIC . 'theme' . DS;
                $result = $file->handle_dir($app_theme_dir, $theme_dir, 'copy', true);
                if ($result == false) {
                    return [RESULT_ERROR, '复制模板文件失败'];
                    exit;
                }
                dlog('5、同步模板');
            }

            //6、判断是公共文件
            $app_theme_dir = $app_path . '/data/public';//模模板公共目录
            if (is_dir($app_theme_dir)) {
                $theme_dir = PATH_PUBLIC;
                $result = $file->handle_dir($app_theme_dir, $theme_dir, 'copy', true);
                if ($result == false) {
                    throw_response_error('模模板公共目录失败');
                }
                dlog('6、判断是公共文件，复制公共文件');
            }

            //10、开启模块,
            $updata = ['status' => 1, 'visible' => 1];
            $result = $this->modelTenModule->updateInfo(['id' => $sys_mid], $updata);

            dlog('app安装执行=》结束=====');
            dlog($result);
            return [RESULT_SUCCESS, '应用插件安装部署成功'];

        } else {
            return [RESULT_ERROR, '模块目录中模块信息文件info.php不存在'];
            exit;
        }
    }

}
